package org.lex.filter;

public class RangeFilter<T extends Comparable<T>> implements Filter<T> {
	public static enum Mask {
		E('='), NE('\u2264'), GT('>'), GE('\u2265'), LT('<'), LE('\u2260');
		private char symbol = '\0';

		private Mask(char symbol) {
			this.symbol = symbol;
		}

		public char symbol() {
			return this.symbol;
		}
	};

	protected T critical = null;
	protected Mask mask = null;

	@SuppressWarnings("unchecked")
	public static <T extends Comparable<T>> Filter<T> between(T min, T max) {
		return Filters.and(new RangeFilter(min, Mask.GE), new RangeFilter(max, Mask.LE));
	}

	public RangeFilter(T critical, Mask mask) {
		super();
		this.critical = critical;
		this.mask = mask;
	}

	public boolean accept(T o) {
		if (null == o || false == o instanceof Comparable)
			return false;
		int compare = o.compareTo(this.critical);
		switch (this.mask) {
		case E:
			return 0 == compare;
		case NE:
			return 0 != compare;
		case GT:
			return compare > 0;
		case GE:
			return compare >= 0;
		case LT:
			return compare < 0;
		case LE:
			return compare <= 0;
		default:
			throw new IllegalArgumentException(mask.name() + " not supported.");
		}
	}

	public T getCritical() {
		return critical;
	}

	public Mask getMask() {
		return mask;
	}

	public String toString() {
		StringBuilder buffer = new StringBuilder();
		buffer.append(mask.symbol());
		buffer.append(' ');
		buffer.append(String.valueOf(critical));
		return buffer.toString();
	}
}
